package logic

import (
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
)

// SSHConfig 定义SSH连接所需的配置信息
type SSHConfig struct {
	User     string
	Password string
	Host     string
	Port     int
}

// UploadFile 通过SSH将本地文件上传到远程服务器
func UploadFile(config SSHConfig, localPath, remotePath string, uncompress bool) error {
	// 构建SSH连接配置
	sshConfig := &ssh.ClientConfig{
		User: config.User,
		Auth: []ssh.AuthMethod{
			ssh.Password(config.Password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 注意：在生产环境中不要使用此选项，应验证主机密钥
		Timeout:         30 * time.Second,
	}

	// 构建SSH连接地址
	address := fmt.Sprintf("%s:%d", config.Host, config.Port)

	// 建立SSH连接
	client, err := ssh.Dial("tcp", address, sshConfig)
	if err != nil {
		return fmt.Errorf("failed to dial: %v", err)
	}
	defer client.Close()
	// 打开一个新的SFTP会话
	sftpClient, err := sftp.NewClient(client)
	if err != nil {
		return fmt.Errorf("failed to create sftp client: %v", err)
	}
	defer sftpClient.Close()

	// 打开本地文件
	localFile, err := os.Open(localPath)
	if err != nil {
		return fmt.Errorf("failed to open local file: %v", err)
	}
	defer localFile.Close()

	// 创建远程文件
	remoteFile, err := sftpClient.Create(remotePath)
	if err != nil {
		return fmt.Errorf("failed to create remote file: %v", err)
	}
	defer remoteFile.Close()

	// 将本地文件内容复制到远程文件
	fmt.Println("开始上传")
	_, err = io.Copy(remoteFile, localFile)
	if err != nil {
		return fmt.Errorf("failed to copy file: %v", err)
	} else {
		fmt.Println("上传结束")
	}
	if uncompress {
		fmt.Println("开始解压,请确保远程服务器已安装unzip等解压命令")
		// 新增解压逻辑
		if err := uncompressFile(client, remotePath); err != nil {
			log.Fatalf("文件解压失败: %v", err)
		}
		fmt.Println("文件解压成功")
	}
	return nil
}

// 解压函数
func uncompressFile(conn *ssh.Client, remotePath string) error {
	// 获取文件信息
	ext := strings.ToLower(filepath.Ext(remotePath))
	remoteDir := filepath.Dir(remotePath)
	//  强制转化为斜杠
	remoteDir = strings.ReplaceAll(remoteDir, string(os.PathSeparator), "/")
	// 构造解压命令
	var cmd string
	switch ext {
	case ".zip":
		cmd = fmt.Sprintf("unzip -o '%s' -d '%s'", remotePath, remoteDir)
	case ".tar.gz", ".tgz":
		cmd = fmt.Sprintf("tar xzf '%s' -C '%s'", remotePath, remoteDir)
	case ".tar.xz", ".txz":
		cmd = fmt.Sprintf("tar xJf '%s' -C '%s'", remotePath, remoteDir)
	case ".tar.bz2", ".tbz2":
		cmd = fmt.Sprintf("tar xjf '%s' -C '%s'", remotePath, remoteDir)
	case ".tar":
		cmd = fmt.Sprintf("tar xf '%s' -C '%s'", remotePath, remoteDir)
	case ".gz":
		cmd = fmt.Sprintf("gunzip -f '%s'", remotePath)
	default:
		return fmt.Errorf("unsupported file type: %s", ext)
	}

	// 创建SSH会话
	session, err := conn.NewSession()
	if err != nil {
		return fmt.Errorf("创建会话失败: %w", err)
	}
	defer session.Close()

	// 执行解压命令
	output, err := session.CombinedOutput(cmd)
	if err != nil {
		return fmt.Errorf("命令执行失败: %w\n输出: %s, 建议安装unzip等压缩命令", err, output)
	} else {
		fmt.Println("解压成功，输出: ", string(output))
	}
	return nil
}
